package com.hulk.dryad.manage.framework.storage;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.hulk.dryad.common.util.WebUtils;
import com.hulk.dryad.manage.boot.upload2.DryadUploadProperties;
import com.hulk.dryad.manage.framework.storage.config.StorageProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.stream.Stream;

/**
 * 服务器本地对象存储服务
 * @author hulk
 */
@Slf4j
@RequiredArgsConstructor
public class LocalStorage implements Storage {

	private final DryadUploadProperties dryadUploadProperties;
	private final StorageProperties storageProperties;

    @Override
    public void store(InputStream inputStream, String contextType, String filename , String directory, String baseDir) {
		baseDir = getSavePath( baseDir);
        try {
			Path path = Paths.get(baseDir,directory,filename);
		    File uploadFile = path.toFile();
			if (uploadFile.exists()) {
				Files.delete(uploadFile.toPath());
			}
			File uploadDir = uploadFile.getParentFile();
			if (!uploadDir.exists()) {
				uploadDir.mkdirs();
			}
            Files.copy(inputStream, path, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            throw new RuntimeException("Failed to store file " + filename, e);
        }
    }

    @Override
    public Stream<Path> loadAll(String directory,String baseDir) {
		baseDir = getSavePath( baseDir);
        try {
			Path rootLocation = Paths.get(baseDir,directory);
            return Files.walk(rootLocation, 1)
                    .filter(path -> !path.equals(rootLocation))
                    .map(path -> rootLocation.relativize(path));
        } catch (IOException e) {
            throw new RuntimeException("Failed to read stored files", e);
        }

    }

    @Override
    public Path loadPath(String filename , String directory, String baseDir) {
		baseDir = getSavePath( baseDir);
        return Paths.get(baseDir,directory,filename);
    }
	@Deprecated
    @Override
    public Resource loadAsResource(String filename , String directory,String baseDir) {
		baseDir = getSavePath( baseDir);
        try {
			Path path = Paths.get(baseDir,directory,filename);
            Resource resource = new UrlResource(path.toUri());
            if (resource.exists() || resource.isReadable()) {
                return resource;
            } else {
                return null;
            }
        } catch (MalformedURLException e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }


	@Override
	public InputStream loadAsInputStream(String filename, String directory, String baseDir)  {
		baseDir = getSavePath( baseDir);
		Path path = Paths.get(baseDir,directory,filename);
		return FileUtil.getInputStream(path.toFile());
	}

	@Override
    public void delete(String filename , String directory,String baseDir) {
		baseDir = getSavePath( baseDir);
		Path path = Paths.get(baseDir,directory,filename);
        try {
            Files.deleteIfExists(path);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public String generateUri(String filename , String directory,String bucket) {
	    String	mapping = WebUtils.getRequest().getRequestURI();
		Path path = Paths.get(mapping,directory,filename);
        return path.toString();
    }

	@Override
	public String getHost(String filename, String directory, String bucket) {
		HttpServletRequest request = WebUtils.getRequest();
		String urlStr =request.getRequestURL().toString();
		URL url = URLUtil.url(urlStr);
		String host = URLUtil.getHost(URLUtil.url(urlStr)).toString();
		int port = url.getPort();
		if(port < 0){
			return host;
		}
		return host+StrUtil.COLON + port;
	}

	@Override
    public  StorageProperties getProp() {
	    return storageProperties;
    }

	private String getSavePath(String baseDir){
		String savePath = Paths.get(dryadUploadProperties.getSavePath()).toString();
		return StrUtil.isBlank(baseDir) ? savePath :baseDir;
	}

}